// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-04-02

package table

type (
	// Table
	// 表格.
	Table interface {
		// GetHead
		// 表头.
		GetHead() Head

		// GetBody
		// 表体.
		GetBody() Body

		// GetColumns
		// 表列数.
		GetColumns() int

		// GetTitle
		// 表标题.
		GetTitle() string

		// GetWidth
		// 表列宽.
		GetWidth(index int) int

		// GetWidths
		// 表各列宽.
		GetWidths() map[int]int

		// SetBody
		// 设置表体.
		SetBody(body Body) Table

		// SetHead
		// 设置表头.
		SetHead(head Head) Table

		// SetTitle
		// 设置标题.
		SetTitle(title string) Table
	}

	table struct {
		length int
		width  map[int]int
		head   Head
		body   Body
		title  string
	}
)

// NewTable
// 创建表格.
func NewTable() Table {
	return &table{
		width: make(map[int]int),
	}
}

// +---------------------------------------------------------------------------+
// | Interface methods                                                         |
// +---------------------------------------------------------------------------+

func (o *table) GetBody() Body               { return o.body }
func (o *table) GetColumns() int             { return o.length }
func (o *table) GetHead() Head               { return o.head }
func (o *table) GetTitle() string            { return o.title }
func (o *table) GetWidth(index int) int      { return o.getWidth(index) }
func (o *table) GetWidths() map[int]int      { return o.width }
func (o *table) SetBody(body Body) Table     { o.body = body; return o.calc() }
func (o *table) SetHead(head Head) Table     { o.head = head; return o.calc() }
func (o *table) SetTitle(title string) Table { o.title = title; return o }

// +---------------------------------------------------------------------------+
// | Access methods                                                            |
// +---------------------------------------------------------------------------+

func (o *table) calc() Table {
	if o.head != nil {
		o.calculate(o.head.GetRow().GetWidths())
	}
	if o.body != nil {
		o.calculate(o.body.GetWidths())
	}
	return o
}

func (o *table) calculate(width map[int]int) {
	for k, v := range width {
		if n, ok := o.width[k]; ok {
			if v > n {
				o.width[k] = v
			}
		} else if o.width[k] < v {
			o.width[k] = v
		}
	}
}

func (o *table) getWidth(index int) int {
	if index >= 0 && index < o.length {
		return o.width[index]
	}
	return 0
}
